//
//  AliyunOSSManager.m
//  GSBlockChain
//
//  Created by guoshikeji_a on 2018/11/30.
//  Copyright © 2018 guoshikeji. All rights reserved.
//

#import "AliyunOSSManager.h"

//获取应用关于aliyunOSS的配置请求
#import "AliyunOSSConfigurationRequest.h"


@interface AliyunOSSManager () {
    AliyunOSSConfigurationData *_ossTokenData;
}

/**
 *OSSClient
 */
@property (nonatomic, strong) OSSClient *ossClient;

@end

@implementation AliyunOSSManager


static AliyunOSSManager *_aliyunOSSManager = nil;
+ (instancetype)sharedOSS {
    static dispatch_once_t ossToken;
    dispatch_once(&ossToken, ^{
        _aliyunOSSManager = [[AliyunOSSManager alloc] init];
    });
    return _aliyunOSSManager;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        //
        [self requestOSSToken];
    }
    return self;
}
#pragma mark - get
- (AliyunOSSConfigurationData *)ossCofigurationData {
    return _ossTokenData;
}

#pragma mark - actions
//请求OSS配置
- (void)requestOSSToken {
    AliyunOSSConfigurationRequest *request = [AliyunOSSConfigurationRequest new];
    request.uuid = [GeneralParameterManager sharedGeneral].uuid;
    //
    WEAK_SELF
    [request didRequestSuccessed:^(id result, id page) {
        AliyunOSSConfigurationResponse *resp = result;
        [wself setOSSTokenData:resp];
        //
    }];
    [request didRequestFailed:^(NSError *error) {
        
    }];
    [request requestServer];
}
- (void)setOSSTokenData:(AliyunOSSConfigurationResponse *)resp {
    if (resp.data) {
        _ossTokenData = resp.data;
        [self initOSSClient:_ossTokenData];
    }
}
- (void)initOSSClient:(AliyunOSSConfigurationData *)data {
    [OSSLog enableLog];
    //
    id <OSSCredentialProvider> credential = [[OSSStsTokenCredentialProvider alloc] initWithAccessKeyId:data.AccessKeyId
                                                                                           secretKeyId:data.AccessKeySecret
                                                                                         securityToken:data.SecurityToken];
    OSSClientConfiguration * conf = [OSSClientConfiguration new];
    conf.maxRetryCount = 3; // 网络请求遇到异常失败后的重试次数
    conf.timeoutIntervalForRequest = 30; // 网络请求的超时时间
    conf.timeoutIntervalForResource = 24 * 60 * 60; // 允许资源传输的最长时间
    //
    self.ossClient = [[OSSClient alloc] initWithEndpoint:data.endpoint
                                      credentialProvider:credential
                                     clientConfiguration:conf];
}

/**
 处理上传文件结果
 */
- (__nullable id)handlePutObjectResponseWith:(OSSPutObjectRequest *)request
                                        task:(OSSTask *)task
                                    complete:(OSSPutObjectCompleteBlock)complete
{
    if (complete) {
        if (task.error) {
            complete(nil,task.error);
        }else {
            AliyunOSSPutResponseObject *responseObject = [AliyunOSSPutResponseObject new];
            //
            responseObject.fileURLPath = [NSString stringWithFormat:@"%@/%@",self.ossCofigurationData.base_url,request.objectKey];
            //
            complete(responseObject,nil);
        }
    }
    return nil;
}


/**
 上传文件
 */
- (OSSTask *)putObject:(AliyunOSSPutObject *)object
           putProgress:(OSSNetworkingUploadProgressBlock)progress
            retryBlock:(OSSNetworkingRetryBlock)retryBlock
              complete:(OSSPutObjectCompleteBlock)complete
{
    OSSPutObjectRequest *request = [OSSPutObjectRequest new];
    //manager级别参数
    request.bucketName = _ossTokenData.bucket;
    //数据层参数
    request.objectKey = [object directoryObjectKeyPath];
    
    if (object.uploadingData) {
        request.uploadingData = object.uploadingData;
    }else if (object.uploadingFileURL) {
        request.uploadingFileURL = object.uploadingFileURL;
    }
    //progress
    if (progress) {
        request.uploadProgress = progress;
    }
    //retry
    if (retryBlock) {
        request.uploadRetryCallback = retryBlock;
    }
    //put
    OSSTask *requestTask = [self.ossClient putObject:request];
    WEAK_SELF
    [requestTask continueWithBlock:^id _Nullable(OSSTask * _Nonnull task) {
        return [wself handlePutObjectResponseWith:request task:task complete:complete];
    }];
    //
    return requestTask;
}
- (OSSTask *)putObject:(AliyunOSSPutObject *)object
           putProgress:(OSSNetworkingUploadProgressBlock)progress
              complete:(OSSPutObjectCompleteBlock)complete {
    return [self putObject:object putProgress:progress retryBlock:nil complete:complete];
}
- (OSSTask *)putObject:(AliyunOSSPutObject *)object
              complete:(OSSPutObjectCompleteBlock)complete {
    return [self putObject:object putProgress:nil retryBlock:nil complete:complete];
}



- (void)putObjects:(NSArray<AliyunOSSPutObject *> *)objects {
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    queue.maxConcurrentOperationCount = objects.count;//1 串行 >1并行
    AliyunOSSConfigurationData *ossTokenData = _ossTokenData;
    __weak typeof(self) wself = self;
    for (int i=0;i<objects.count;i++) {
        AliyunOSSPutObject *object = objects[i];
        if (object&&[object isKindOfClass:AliyunOSSPutObject.class]) {
            NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
                //任务执行
                OSSPutObjectRequest *request = [OSSPutObjectRequest new];
                //manager级别参数
                request.bucketName = ossTokenData.bucket;
                //数据层参数
                request.objectKey = [object directoryObjectKeyPath];
                
                if (object.uploadingData) {
                    request.uploadingData = object.uploadingData;
                }else if (object.uploadingFileURL) {
                    request.uploadingFileURL = object.uploadingFileURL;
                }
                //put
                OSSTask *requestTask = [wself.ossClient putObject:request];
                [requestTask waitUntilFinished]; // 阻塞直到上传完成
                if (!requestTask.error) {
                    NSLog(@"upload object success! %@",[NSThread currentThread]);
                    NSLog(@"%@",[NSString stringWithFormat:@"%@/%@",wself.ossCofigurationData.base_url,request.objectKey]);
                } else {
                    NSLog(@"upload object failed, error: %@" , requestTask.error);
                    //上传失败一个 也等同于全部失败
                    [queue cancelAllOperations];
                    
                    return;
                }
                if (object==objects.lastObject) {
                    //完成b全部上传
                }
            }];
            if (queue.operations.count != 0) {//依赖上一个operation执行
                [operation addDependency:queue.operations.lastObject];
            }
            [queue addOperation:operation];//添加并执行
        }
    }
}

@end
